# coding: utf-8
import random

from qcloudsms_py import SmsSingleSender
from qcloudsms_py.httpclient import HTTPError
from fraMail.framail import FraMail
from fralog.FraLog import Fralog
# from fralog.kafka_logger import KafkaLogger
from module_questions.customer_combine import *
from settings import *
from flask import request, make_response, Response
import RedisOper

from access_control.access_control import *
from globalsettings import *

LOG = Fralog().getFileLog()

APP_ID = '1400066468'
APP_KEY = '4581214ef64d4c13dee0af7bea2d5a2f'


class SMS(object):
    # 0 为普通短信  1 为营销短信
    sms_type = 0
    ssender = SmsSingleSender(APP_ID, APP_KEY)

    def __init__(self):
        super(SMS, self).__init__()

    def _send_msg(self, msg, recv):
        '''
        
        :param msg: 
        :param recv: 
        :return: 
        '''
        try:
            result = self.ssender.send(sms_type=self.sms_type, nation_code=86, phone_number=recv, msg=msg, extend='',
                                       ext='')
            print(result)
        except HTTPError as e:
            LOG.error(e)
        except Exception as e:
            LOG.error(e)

    def _send_msg_with_params(self, recv, hospital, template, sign, url):
        """
        调用Python的带参数发送接口
        :param msg_type 短信类型 0 普通短信； 1 营销短信
        :param msg:
        :param recv:
        :param template:
        :param sign:
        :return:
        """
        return self.ssender.send_with_param(nation_code=86, phone_number=recv, template_id=template,
                                            params=[hospital, url], sign=sign)

    def send_shulin(self, phone, hospital, url):
        # old 173850 new 190676
        return self._send_msg_with_params(recv=phone, hospital=hospital, template='190676', sign='北京大学首钢医院', url=url)

    def send_verify_code(self, cellphone, code, timeout='15'):
        '''
        
        :param cellphone: 
        :param code: 
        :param timeout: 
        :return: 
        '''
        msg = '%s为您的验证码，请于%s分钟内填写。如非本人操作，请忽略本短信' % (code, timeout)
        LOG.debug('SMS Message: %s' % msg)
        self._send_msg(msg=msg, recv=cellphone)

    def send_try_account(self, cellphone, password):
        '''
        
        :param cellphone: 
        :param password: 
        :return: 
        '''
        msg = '您试用账号的登录密码为%s，账号为您的手机号码。' % (password)
        self._send_msg(msg=msg, recv=cellphone)

    # 您账号的登录密码为%s，账号为您的手机号码

    def send_reset_pwd(self, cellphone, password):
        '''
        :param cellphone:
        :param password:
        :return:
        '''
        msg = '您账号的登录密码为%s，账号为您的手机号码。' % (password)
        self._send_msg(msg=msg, recv=cellphone)


# 生成4位数字验证码
def create_verify_code():
    # 验证码4位
    rand = random.Random()
    ret = ''
    for i in range(SMS_VCODE_LEN):
        pos = int(rand.random() * 10)
        ret += str(pos)
    return ret


#
# 生成随机密码
def create_random_pwd():
    seed = "0 1 2 3 4 5 6 7 8 9".split(' ')
    random.shuffle(seed)
    print(seed)
    return ''.join(seed[0:SMS_PWD_LEN])


#
# 生成随机密码
def create_4numrandom_pwd():
    seed = "0 1 2 3 4 5 6 7 8 9".split(' ')
    random.shuffle(seed)
    print(seed)
    return ''.join(seed[0:4])


FRA_SMS = SMS()


@app.route('/sms/shulin/<phone>/<hospital>/<url>', methods=['GET'])
def send_shulin(phone, hospital, url):
    ret = FRA_SMS.send_shulin(phone, hospital, url)
    result = ret.get('result')
    if result == 0:
        LOG.write_log(msg='ok', event='shulin_sms_ok', product_id='shulin')
    else:
        LOG.write_log(msg='fail', event='shulin_sms_fail', product_id='shulin')
    return result


@app.route('/sms/verify/<phone>', methods=['GET'])
def send_verify(phone):
    key = phone + '_sms'
    code = create_verify_code()
    LOG.write_log('ask for sms code', event='sms_verify', phone=phone)
    if REDIS.get(key) is None:
        LOG.debug('code is: %s, send message' % (code))
        REDIS.set(key, code)
        REDIS.expire(key, SMS_TIMEOUT)
        FRA_SMS.send_verify_code(phone, code)
    else:
        LOG.debug('return code directly')
        code = REDIS.get(key).encode('utf-8')
    return code


@app.route('/sms/verify4answer/<phone>', methods=['GET'])
def send_verify4answer(phone):
    key = 'v4a_' + phone
    code = create_4numrandom_pwd()
    LOG.write_log('ask for sms code 4 answer', event='sms_verify', phone=phone)
    if REDIS.get(key) is None:
        LOG.debug('code is: %s, send message' % (code))
        REDIS.set(key, code)
        REDIS.expire(key, 10)
        FRA_SMS.send_verify_code(phone, code)
    else:
        LOG.debug('return code directly')
        code = REDIS.get(key).encode('utf-8')
    return code


@app.route('/sms/check/<phone>/<code>', methods=['GET'])
def check_code(phone, code):
    LOG.info("客户端提供的验证码为: %s" % code)
    realcode = REDIS.get(phone + '_sms')
    LOG.info("系统中存储的验证码为: %s" % realcode)
    ret = deepcopy(g_ret)
    ret['msg_flag'] = 'OK'

    if realcode == code:
        ret['code'] = 200
    else:
        ret['code'] = 500

    return json.dumps(ret)


@app.route('/sms/account/<phone>/<product>/<company>/<code>')
def send_account(phone, product, company, code):
    ret = deepcopy(g_ret)
    LOG.write_log('send try account', event='try', product_id=product, user=phone)
    key = phone + '_account'
    user_exist = REDIS.havekey(key)

    param = get_param(request)
    email = param.get('email')

    LOG.debug('客户Email: %s' % (email))

    if check_new_user(phone) > 0:
        ret['code'] = 500
        ret['msg'] = '用户已存在'
        return json.dumps(ret)

    pwd = create_random_pwd()
    create_new_user(user=phone, pwd=pwd, product_id=product, company_id=company, code=code, limit_times=TRY_TIMES_LIMIT,
                    email=email)
    try:
        mail = FraMail()
        mail.login()
        # send_file(filename, to, title, msg):
        msg_title = '用户： （' + str(phone) + '）<br>\r\n' + '公司： ' + str(company) + \
                    '<br>\r\n' + '于 ' + time.strftime('%Y-%m-%d %H:%M:%S',
                                                      time.localtime(time.time())) + '试用了伯乐产品<br>\r\n'
        msg_mail = '备注详细内容  电话:' + str(phone) + ',  密码:' + str(pwd) + ',  产品:' + str(product) + ',  公司:' + str(
            company) + '  ,问卷编码:' + str(code) + ',  邮箱:' + str(email) + ',  限制次数:' + str(TRY_TIMES_LIMIT)
        mail.send(sendto='xuan.feng@unidt.com', content=msg_title + msg_mail, title='客户注册试用bole产品')
        mail.send(sendto='xiaodong.yang@unidt.com', content=msg_title + msg_mail, title='客户注册试用bole产品')
        mail.send(sendto='yue.zhuo@unidt.com', content=msg_title + msg_mail, title='客户注册试用bole产品')
    except Exception as e:
        LOG.debug('发送Email错误: %s' % str(e))
    ret['code'] = 200
    ret['msg'] = '账号已生成'
    FRA_SMS.send_try_account(phone, pwd)
    REDIS.set(key, pwd)
    return json.dumps(ret)


@app.route('/sms/check_pwd', methods=['GET', 'POST'])
@verify_token
def check_pwd():
    '''
    验证密码是否正确
    :return:
    '''

    ret = deepcopy(g_ret)
    param = get_param(request)
    user = param.get('user')
    oldPwd = param.get('oldPwd')
    LOG.debug('查询密码开始！')
    user_info = db.t_user.find_one({'user_id': user, 'pwd': md5(oldPwd)})
    if user_info is not None:
        ret['code'] = 200
        ret['msg'] = '密码验证正确'
    else:
        ret['code'] = 500
        ret['msg'] = '密码验证失败'
    return json.dumps(ret)


@app.route('/sms/get_deadLine_state', methods=['GET', 'POST'])
@verify_token
def get_deadLine_state():
    '''
     获取用户截止日期和用户状态
      是否 会员
    :return:
    '''

    ret = deepcopy(g_ret)
    param = get_param(request)
    user = param.get('user')
    LOG.debug('查询截止日期和会员状态开始！')
    user_info = db.t_user.find_one({'user_id': user})
    # KafkaLogger().log_event(event='a_api', app='p_aggent', user=user, level='info', msg='获取用户截止日期和用户状态',
    #                         status='200')
    if user_info is not None:
        user_limit = db.t_user_limit.find_one({'user_id': user})
        ret['code'] = 200
        ret['dead_line'] = user_limit.get('dead_line')
        ret['acount_type'] = user_info.get('acount_type')
        ret['msg_flag'] = 'success'
    else:
        ret['code'] = 500
        ret['msg'] = '当前用户不存在！'
    return json.dumps(ret)


@app.route('/sms/get_plans', methods=['GET', 'POST'])
@verify_token
def insure_get_plans():
    '''
       根据产品编号和渠道编号，获取收费方案
    :return:
    '''
    ret = deepcopy(g_ret)
    param = get_param(request)
    channel_no = param.get('channel_no')
    # product = param.get('product_id')
    product = 'insure'
    plans = []
    pay_plan = db.t_pay_plan.find({'channel_no': channel_no})
    if pay_plan is not None:
        for plan in pay_plan:
            if '_id' in plan:
                del plan['_id']
            plans.append(plan)
        ret['code'] = 200
        ret['data'] = plans
        ret['msg'] = '查询成功!'
    return json.dumps(ret)


@app.route('/order/pay_online', methods=['GET', 'POST'])
# @verify_token
def pay_online():
    # 支付接口
    LOG.debug('保险经纪续费支付接口！')
    ret = deepcopy(g_ret)
    param = get_param(request)
    user = param.get('user')
    guid = param.get('guid')
    channel_no = param.get('channel_no')
    plan_no = param.get('plan_no')
    # KafkaLogger().log_event(event='a_api', app='p_aggent', user=user, level='info', msg=str(channel_no) + '保险经纪续费支付接口',
    #                         status='200')
    if user is None or user == '':
        ret['code'] = 400
        ret['msg'] = '用户不可为空！'
        return json.dumps(ret)
    if guid is None or guid == '':
        ret['code'] = 400
        ret['msg'] = '授权失败，请重新登录！'
        return json.dumps(ret)
    if channel_no is None or channel_no == '':
        ret['code'] = 400
        ret['msg'] = '渠道不可为空！'
        return json.dumps(ret)
    if plan_no is None or plan_no == '':
        ret['code'] = 400
        ret['msg'] = '方案不可为空！'
        return json.dumps(ret)   
    user_info = db.t_user.find_one({'user_id': user, 'channel_no': channel_no})
    if user_info is None:
        ret['code'] = 400
        ret['msg'] = '用户不存在！'
        return json.dumps(ret)
    pay_plan = db.t_pay_plan.find_one({'plan_no': plan_no, 'channel_no': channel_no})
    if pay_plan is None:
        ret['msg'] = '方案不存在，下单失败！'
        return json.dumps(ret)
    amount = pay_plan.get('total_amount')
    add_month = pay_plan.get('add_month')
    order_no = get_pay_onlie(user=user, plan_no=plan_no, guid=guid, channel_no=channel_no, amount=amount,
                             add_month=add_month)
    if order_no is not None:
        ret['code'] = 200
        ret['msg_flag'] = 'success'
        ret['order_no'] = order_no
        ret['msg'] = '新增支付记录!'
    return json.dumps(ret)


@app.route('/order/get_order', methods=['GET', 'POST'])
# @verify_token
def get_order_insure():

    LOG.debug('预付款下单，生成订单号！')
    ret = deepcopy(g_ret)
    param = get_param(request)
    order_no = param.get('order_no')
    pay_order = db.t_pay_order.find_one({'order_no': order_no})

    if pay_order is None:
        ret['code'] = 400
        ret['msg'] = '用户不存在！'
        return json.dumps(ret)
    if '_id' in pay_order:
        del pay_order['_id']
    user = pay_order['user_id']
    # KafkaLogger().log_event(event='a_api', app='p_aggent', user=user, level='info', msg=str(order_no) + '预付款下单，生成订单号',
    #                         status='200')
    if order_no is not None:
        ret['code'] = 200
        ret['msg_flag'] = 'success'
        ret['data'] = pay_order
        ret['msg'] = '查询订单成功!'
    return json.dumps(ret)


@app.route('/order/updatePayStatus', methods=['GET', 'POST'])
# @verify_token
def insure_pay_update():
    '''
       微信支付成功回调，修改支付状态
    :return:
    '''
    ret = deepcopy(g_ret)
    param = get_param(request)
    order_no = param.get('order_no')
    LOG.debug('支付回调更新支付状态开始！: %s' % str(order_no))
    pay_line = db.t_pay_order.find_one(
        {'order_no': order_no, 'status': 0})
    if pay_line is None:
        LOG.debug('预支付记录存在！: %s' % str(order_no))
        ret['code'] = 400
        ret['msg'] = '记录不存在！'
        return json.dumps(ret)
    user = pay_line.get('user_id')
    channel_no = pay_line.get('channel_no')
    # KafkaLogger().log_event(event='a_api', app='p_aggent', user=user, level='info', msg=str(channel_no) + '更新续费订单状态',
    #                         status='200')
    LOG.debug('用户编号：: %s' % str(user))
    user_info = db.t_user.find_one({'user_id': user, 'channel_no': channel_no})
    if user_info is None:
        ret['code'] = 400
        ret['msg'] = '用户不存在！'
        LOG.debug('用户不存在，支付失败！')
        return json.dumps(ret)
    acount_type = user_info['acount_type']
    if pay_line is not None and acount_type is not '':
        month = pay_line.get('add_month')
        if month is not None:
            up_line = get_pay_update(user=user, order_no=order_no, channel_no=channel_no, acount_type=acount_type,
                                     month=month)
            if up_line == 1:
                ret['code'] = 200
                ret['msg_flag'] = 'success'
                ret['msg'] = '更新成功!'

    return json.dumps(ret)


@app.route('/sms/get_code', methods=['GET', 'POST'])
def getCode():
    ret = deepcopy(g_ret)
    param = get_param(request)
    code = param.get('code')
    code_list = db.responses_collection.find({'code': code})
    res = []
    if code_list is not None:
        for open in code_list:
            re = []
            openid = open.get("response").get("wxid")
            # re["openid"] = openid
            res.append(openid)
        ret['code'] = 200
        ret['data'] = res
        ret['msg'] = '查询成功!'
    return json.dumps(ret)


@app.route('/sms/edit_pwd', methods=['GET', 'POST'])
@verify_token
def edit_pwd():
    '''
     修改密码
    :return:
    '''
    LOG.debug('修改密码开始！')
    ret = deepcopy(g_ret)
    param = get_param(request)
    user = param.get('user')
    oldPwd = param.get('oldPwd')
    pwd = param.get('newPwd')
    product = 'insure'
    # KafkaLogger().log_event(event='a_api', app='p_aggent', user=user, level='info', msg=str(product)+'修改密码开始',
    #                         status='200')
    item = db.t_user_product.find_one({'user_id': user, 'product_id': product})
    if item is not None:
        user_info = db.t_user.find_one({'user_id': user, 'pwd': md5(oldPwd)})
        if user_info is None:
            ret['code'] = 400
            ret['msg'] = '原始密码错误！'
        else:
            db.t_user.update({'user_id': user}, {'$set': {'pwd': md5(pwd)}})
            ret['code'] = 200
            ret['msg'] = '新密码修改成功！'
    else:
        ret['code'] = 500
        ret['msg'] = '用户不存在！'

    return json.dumps(ret)


@app.route('/sms/forget_pwd', methods=['GET', 'POST'])
def forget_pwd():
    '''
       根据商品编号、公司id 和用户名 查找唯一用户手机号
       进行重置密码并发送短信告知
    :param product:
    :param company:
    :param userid:
    :return:
    '''
    ret = deepcopy(g_ret)
    param = get_param(request)
    user = param.get('user')
    # 判断产品下用户是否存在
    # 判断公司下产品
    log.debug('查询公司名称')
    product = 'insure'  # insure
    if user is not None and user is not '':
        items = db.t_user_product.find_one({'user_id': user, 'product_id': product}, sort=[('user_id', -1)])
        if items is not None:
            pwd = create_random_pwd()
            phone = user
            FRA_SMS.send_reset_pwd(phone, pwd)
            db.t_user.update({'user_id': user}, {'$set': {'pwd': md5(pwd)}})
            # 获取公司名称或公司guid
            ret['code'] = 200
            ret['msg'] = '密码重置成功，已短信发送您的手机，请注意查收！'
        else:
            ret['code'] = 500
            ret['msg'] = '当前用户不存在，请先注册！'
            log.debug('不存在当前用户')
    return json.dumps(ret)


@app.route('/api/sms/accountapi/<phone>/<product>/<company>', methods=['GET', 'POST'])
def send_account_api(phone, product, company):
    param = get_param(request)
    ret = deepcopy(g_ret)
    appkey = str(param.get('appkey'))
    limit_times = param.get('limit_times')
    f_company_id = ''
    if appkey in APP_KEY_LIST:
        f_company_id = appkey.split('_')[0]
        LOG.write_log('send try account', event='try', product_id=product, user=phone)
        # key = phone + '_account'
        # user_exist = REDIS.havekey(key)
        email = param.get('email')
        LOG.debug('客户Email: %s' % (email))
        if check_new_user(phone) > 0:
            ret['code'] = 500
            ret['msg'] = '用户已存在'
            return json.dumps(ret)
        pwd = create_random_pwd()
        if limit_times is not None:
            pass
        else:
            limit_times = TRY_TIMES_LIMIT
        create_new_subuser(user=phone, md5pwd=md5(pwd), product_id='hr', company_id=company,
                           p_company=f_company_id, limit_times=limit_times, email=email, acount_type=1)
        #  (user=phone, pwd=pwd, product_id=product, company_id=company, code=code, limit_times=limit_times, email=email)
        try:
            mail = FraMail()
            mail.login()
            # send_file(filename, to, title, msg):
            msg_title = '用户： （' + str(phone) + '）<br>\r\n' + '公司： ' + str(f_company_id) + \
                        '<br>\r\n' + '于 ' + time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())) \
                        + 'API 调用了伯乐产品<br>\r\n'
            msg_mail = '备注详细内容  电话:' + str(phone) + ',  密码:' + str(pwd) + ',  产品:' + str(product) + ',  公司:' + str(
                f_company_id) + ',  邮箱:' + str(email) + ',  限制次数:' + str(TRY_TIMES_LIMIT)
            # mail.send(sendto='xiaodong.yang@unidt.com', content=msg_title + msg_mail, title=f_company_id + '子客户调用api使用产品')
            # mail.send(sendto='yue.zhuo@unidt.com', content=msg_title + msg_mail, title=f_company_id + '子客户调用api使用产品')
        except Exception as e:
            LOG.debug('发送Email错误: %s' % str(e))
        ret['code'] = 200
        ret['pwd'] = str(pwd)
        ret['msg'] = '账号已生成'
        # FRA_SMS.send_try_account(phone, pwd)
        # REDIS.set(key, pwd)
        return json.dumps(ret)
    else:
        return json.dumps(ret)


@app.route('/api/sms/account_insure_api', methods=['GET', 'POST'])
def send_account_insure_api():
    '''
        保险经纪人新增账号
        company 默认手机号
        product 默认 产品
    '''
    param = get_param(request)
    ret = deepcopy(g_ret)
    phone = param.get('user')
    if phone is None or phone == '':
        ret['code'] = 400
        ret['msg'] = '用户名不可为空！'
        return json.dumps(ret)
    product = 'insure'
    email = param.get('email')
    code = param.get('code')
    channel_no = param.get('channel_no')
    # KafkaLogger().log_event(event='a_api', app='p_aggent', user=phone, level='info', msg=str(channel_no) + '保险经纪人账号注册',
    #                         status='200')
    LOG.info('渠道编号: %s' % str(channel_no))
    if check_new_user_product(phone, product) > 0:
        ret['code'] = 500
        ret['msg'] = '用户已存在'
        return json.dumps(ret)
    if channel_no is not None or channel_no == '':
        channel = check_new_channel_product(channel_no, product)
        if channel == 0:
            ret['code'] = 500
            ret['msg'] = '渠道不存在'
            return json.dumps(ret)
    f_company_id = ''
    # 企业邀请码验证码
    invitation_code = param.get('invitation_code')
    value = {'user': phone, 'product_id': product}
    pwd = create_random_pwd()
    try:
        if invitation_code is None or invitation_code is "":
            res = customer_combine.insert4BXJJR(value=value)
            if res['code'] == 200:
                survey_code = res['survey_code']
                limit_times = INSURE_TIMES_LIMIT
                LOG.write_log('send try account', event='try', code=survey_code, product_id=product, user=phone)
                flag = create_new_insure_user(user=phone, code=survey_code, pwd=pwd, phone=phone, product_id='insure',
                                              company_id=survey_code, email=email,
                                              limit_times=limit_times, acount_type=1, channel_no=channel_no)
                if flag:
                    ret['code'] = 200
                    ret['msg'] = '账号已生成'
                    FRA_SMS.send_try_account(phone, pwd)
            else:
                ret['code'] = 500
                ret['msg'] = '系统异常，创建失败!'
                ret['msg_flag'] = 'userid is duplication'
        else:
            company_limit = db.t_user_limit.find_one({"company_id": invitation_code})
            if company_limit is None:
                ret['code'] = 500
                ret['msg'] = '邀请码错误！'
                ret['msg_flag'] = 'invitation_code is duplication'
                return json.dumps(ret)
            survey_code = company_limit['code']
            company_id = company_limit['company_id']
            product_id = company_limit['product_id']
            limit_times = company_limit['max_limit']
            flag = create_add_insure_user(user=phone, code=survey_code, pwd=pwd, phone=phone, product_id=product_id,
                                          company_id=company_id, email=email,
                                          limit_times=limit_times, acount_type=2)
            if flag:
                ret['code'] = 200
                ret['msg'] = '账号已生成'
                FRA_SMS.send_try_account(phone, pwd)
        

            else:
                ret['code'] = 404
                ret['msg'] = '创建失败'
                ret['msg_flag'] = 'userid is duplication'
        # mail = FraMail()
        # mail.login()
        # msg_title = '用户： （' + str(phone) + '）<br>\r\n' + '公司： ' + str(f_company_id) + \
        #          '<br>\r\n' + '于 ' + time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())) \
        #          + 'API 调用了保险经纪人产品<br>\r\n'
        # msg_mail = '备注详细内容  电话:' + str(phone) + ',  密码:' + str(pwd) + ',  产品:' + str(product) + ',  公司:' + str(
        #  f_company_id) + ',  邮箱:' + str(email) + ',  限制次数:' + str(INSURE_TIMES_LIMIT)
    except Exception as e:
        LOG.debug('异常错误: %s' % str(e))
        ret['code'] = 500
        ret['msg'] = '异常错误！' + str(e)
    # REDIS.set(key, pwd)
    return json.dumps(ret)


if __name__ == '__main__':
    sms = SMS()
    # ret = sms.send_reset_pwd("15900921541", "BXJJR")
    # print(ret)
    # ret = sms.send_shulin(phone='13761463668',hospital= '北京协和',url='aa')
    # print(ret)
    # sms.send_msg('您本次在华院数据的验证码为762381，2分钟内有效。本验证码仅用于华院数据相关产品的验证，请勿泄露，否则可能会损害您的正常权益。', '15618808660')
    # all = 0
    # for j in range(30):
    #     repeat = {}
    #     rpt_ct = 0
    #     for i in range(500):
    #         code = create_verify_code()
    #         if repeat.get(code) is None:
    #             repeat[code] = 0
    #         else:
    #             rpt_ct += 1
    #     print('重复次数: %d' % rpt_ct)
    #     all += rpt_ct
    # print('平均重复次数: %f'%(all/30.0))
    # REDIS.delete('17317935135_sms')

    # print(create_random_pwd())
